home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / lib / rhythmbox / plugins / lyrics / __init__.pyc (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2009-04-20  |  13.6 KB  |  352 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import os
  5. import re
  6. import gtk
  7. import gtk.glade as gtk
  8. import gconf
  9. import rhythmdb
  10. import rb
  11. import LyricsParse
  12. from LyricsConfigureDialog import LyricsConfigureDialog
  13. ui_str = '\n<ui>\n  <menubar name="MenuBar">\n\t<menu name="ViewMenu" action="View">\n\t  <menuitem name="ViewSongLyrics" action="ViewSongLyrics"/>\n\t</menu>\n  </menubar>\n</ui>\n'
  14. LYRIC_TITLE_STRIP = [
  15.     '\\(live[^\\)]*\\)',
  16.     '\\(acoustic[^\\)]*\\)',
  17.     '\\([^\\)]*mix\\)',
  18.     '\\([^\\)]*version\\)',
  19.     '\\([^\\)]*edit\\)',
  20.     '\\(feat[^\\)]*\\)']
  21. LYRIC_TITLE_REPLACE = [
  22.     ('/', '-'),
  23.     (' & ', ' and ')]
  24. LYRIC_ARTIST_REPLACE = [
  25.     ('/', '-'),
  26.     (' & ', ' and ')]
  27. gconf_keys = {
  28.     'engines': '/apps/rhythmbox/plugins/lyrics/engines',
  29.     'folder': '/apps/rhythmbox/plugins/lyrics/folder' }
  30.  
  31. def create_lyrics_view():
  32.     tview = gtk.TextView()
  33.     tview.set_wrap_mode(gtk.WRAP_WORD)
  34.     tview.set_editable(False)
  35.     tview.set_left_margin(6)
  36.     tview.set_size_request(0, 0)
  37.     sw = gtk.ScrolledWindow()
  38.     sw.add(tview)
  39.     sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
  40.     sw.set_shadow_type(gtk.SHADOW_IN)
  41.     vbox = gtk.VBox(spacing = 12)
  42.     vbox.pack_start(sw, expand = True)
  43.     return (vbox, tview.get_buffer(), tview)
  44.  
  45.  
  46. def parse_song_data(artist, title):
  47.     for exp in LYRIC_ARTIST_REPLACE:
  48.         artist = re.sub(exp[0], exp[1], artist)
  49.     
  50.     for exp in LYRIC_TITLE_REPLACE:
  51.         title = re.sub(exp[0], exp[1], title)
  52.     
  53.     for exp in LYRIC_TITLE_STRIP:
  54.         title = re.sub(exp, '', title)
  55.     
  56.     title = title.strip()
  57.     artist = artist.strip()
  58.     return (artist, title)
  59.  
  60.  
  61. def build_cache_path(artist, title):
  62.     folder = gconf.client_get_default().get_string(gconf_keys['folder'])
  63.     if folder is None:
  64.         folder = os.path.join(rb.user_cache_dir(), 'lyrics')
  65.     
  66.     lyrics_folder = os.path.expanduser(folder)
  67.     if not os.path.exists(lyrics_folder):
  68.         os.mkdir(lyrics_folder)
  69.     
  70.     artist_folder = os.path.join(lyrics_folder, artist[:128])
  71.     if not os.path.exists(artist_folder):
  72.         os.mkdir(artist_folder)
  73.     
  74.     return os.path.join(artist_folder, title[:128] + '.lyric')
  75.  
  76.  
  77. class LyricGrabber(object):
  78.     
  79.     def __init__(self, db, entry):
  80.         self.db = db
  81.         self.entry = entry
  82.         self.artist = self.db.entry_get(self.entry, rhythmdb.PROP_ARTIST).lower()
  83.         self.title = self.db.entry_get(self.entry, rhythmdb.PROP_TITLE).lower()
  84.         (self.artist, self.title) = parse_song_data(self.artist, self.title)
  85.         self.cache_path = build_cache_path(self.artist, self.title)
  86.  
  87.     
  88.     def verify_lyric(self):
  89.         return os.path.exists(self.cache_path)
  90.  
  91.     
  92.     def search_lyrics(self, callback, cache_only = False):
  93.         self.callback = callback
  94.         status = self.verify_lyric()
  95.         if status:
  96.             l = rb.Loader()
  97.             l.get_url(self.cache_path, callback)
  98.         elif cache_only:
  99.             self.callback(_('No lyrics found'))
  100.         else:
  101.             
  102.             def lyric_callback(text):
  103.                 if text is not None:
  104.                     f = file(self.cache_path, 'w')
  105.                     f.write(text)
  106.                     f.close()
  107.                     self.callback(text)
  108.                 else:
  109.                     self.callback(_('No lyrics found'))
  110.  
  111.             parser = LyricsParse.Parser(gconf_keys, self.artist, self.title)
  112.             parser.get_lyrics(lyric_callback)
  113.  
  114.  
  115.  
  116. class LyricPane(object):
  117.     
  118.     def __init__(self, db, song_info):
  119.         self.db = db
  120.         self.song_info = song_info
  121.         self.entry = self.song_info.get_property('current-entry')
  122.         self.build_path()
  123.         
  124.         def save_lyrics(cache_path, text):
  125.             f = file(cache_path, 'w')
  126.             f.write(text)
  127.             f.close()
  128.  
  129.         
  130.         def erase_lyrics(cache_path):
  131.             f = file(cache_path, 'w')
  132.             f.write('')
  133.             f.close()
  134.  
  135.         
  136.         def save_callback():
  137.             buf = self.buffer
  138.             startiter = buf.get_start_iter()
  139.             enditer = buf.get_end_iter()
  140.             text = buf.get_text(startiter, enditer)
  141.             save_lyrics(self.cache_path, text)
  142.             self.get_lyrics()
  143.  
  144.         
  145.         def edit_callback(widget):
  146.             if self.edit.get_active() == 1:
  147.                 self.tview.set_editable(True)
  148.                 self.edit.set_label(_('_Save'))
  149.             elif self.cache_path is not None:
  150.                 save_callback()
  151.             
  152.             self.tview.set_editable(False)
  153.             self.edit.set_label(_('_Edit'))
  154.  
  155.         
  156.         def discard_callback(widget):
  157.             if self.cache_path is not None and os.path.exists(self.cache_path):
  158.                 os.remove(self.cache_path)
  159.             
  160.             self.get_lyrics()
  161.  
  162.         
  163.         def clear_callback(widget):
  164.             if self.cache_path is not None and os.path.exists(self.cache_path):
  165.                 erase_lyrics(self.cache_path)
  166.             
  167.             self.get_lyrics()
  168.  
  169.         self.edit = gtk.ToggleButton(_('_Edit'))
  170.         self.edit.connect('toggled', edit_callback)
  171.         self.discard = gtk.Button(_('_Search again'))
  172.         self.discard.connect('clicked', discard_callback)
  173.         self.clear = gtk.Button(stock = gtk.STOCK_CLEAR)
  174.         self.clear.connect('clicked', clear_callback)
  175.         self.hbox = gtk.HButtonBox()
  176.         self.hbox.set_spacing(6)
  177.         self.hbox.set_layout(gtk.BUTTONBOX_END)
  178.         self.hbox.add(self.edit)
  179.         self.hbox.add(self.clear)
  180.         self.hbox.add(self.discard)
  181.         self.hbox.set_child_secondary(self.clear, is_secondary = True)
  182.         (self.view, self.buffer, self.tview) = create_lyrics_view()
  183.         self.view.pack_start(self.hbox, expand = False, fill = False, padding = 6)
  184.         self.view.set_spacing(2)
  185.         self.view.show_all()
  186.         self.page_num = song_info.append_page(_('Lyrics'), self.view)
  187.         self.have_lyrics = 0
  188.         self.visible = 0
  189.         self.entry_change_id = song_info.connect('notify::current-entry', self.entry_changed)
  190.         nb = self.view.get_parent()
  191.         self.switch_page_id = nb.connect('switch-page', self.switch_page_cb)
  192.  
  193.     
  194.     def build_path(self):
  195.         artist = self.db.entry_get(self.entry, rhythmdb.PROP_ARTIST).lower()
  196.         title = self.db.entry_get(self.entry, rhythmdb.PROP_TITLE).lower()
  197.         (artist, title) = parse_song_data(artist, title)
  198.         cache_path = build_cache_path(artist, title)
  199.         self.cache_path = cache_path
  200.  
  201.     
  202.     def entry_changed(self, pspec, duh):
  203.         self.entry = self.song_info.get_property('current-entry')
  204.         self.have_lyrics = 0
  205.         if self.visible != 0:
  206.             self.build_path()
  207.             self.get_lyrics()
  208.         
  209.  
  210.     
  211.     def switch_page_cb(self, notebook, page, page_num):
  212.         if self.have_lyrics != 0:
  213.             return None
  214.         if page_num != self.page_num:
  215.             self.visible = 0
  216.             return None
  217.         self.visible = 1
  218.         self.get_lyrics()
  219.  
  220.     
  221.     def get_lyrics(self):
  222.         if self.entry is None:
  223.             return None
  224.         self.buffer.set_text(_('Searching for lyrics...'))
  225.         lyrics_grabber = LyricGrabber(self.db, self.entry)
  226.         lyrics_grabber.search_lyrics(self.buffer.set_text)
  227.  
  228.  
  229.  
  230. class LyricWindow(gtk.Window):
  231.     
  232.     def __init__(self):
  233.         gtk.Window.__init__(self)
  234.         self.set_border_width(12)
  235.         close = gtk.Button(stock = gtk.STOCK_CLOSE)
  236.         close.connect(('clicked',), (lambda w: self.destroy()))
  237.         (lyrics_view, buffer, tview) = create_lyrics_view()
  238.         self.buffer = buffer
  239.         bbox = gtk.HButtonBox()
  240.         bbox.set_layout(gtk.BUTTONBOX_END)
  241.         bbox.pack_start(close)
  242.         lyrics_view.pack_start(bbox, expand = False)
  243.         self.add(lyrics_view)
  244.         self.set_default_size(400, 300)
  245.         self.show_all()
  246.  
  247.     
  248.     def s_title(self, title, artist):
  249.         self.set_title(title + ' - ' + artist + ' - ' + _('Lyrics'))
  250.  
  251.  
  252.  
  253. class LyricsDisplayPlugin(rb.Plugin):
  254.     
  255.     def __init__(self):
  256.         rb.Plugin.__init__(self)
  257.         self.window = None
  258.  
  259.     
  260.     def activate(self, shell):
  261.         self.shell = shell
  262.         self.action = gtk.Action('ViewSongLyrics', _('Song L_yrics'), _('Display lyrics for the playing song'), 'rb-song-lyrics')
  263.         self.activate_id = self.action.connect('activate', self.show_song_lyrics, shell)
  264.         self.action_group = gtk.ActionGroup('SongLyricsPluginActions')
  265.         self.action_group.add_action_with_accel(self.action, '<control>L')
  266.         uim = shell.get_ui_manager()
  267.         uim.insert_action_group(self.action_group, 0)
  268.         self.ui_id = uim.add_ui_from_string(ui_str)
  269.         uim.ensure_update()
  270.         sp = shell.get_player()
  271.         self.pec_id = sp.connect('playing-song-changed', self.playing_entry_changed)
  272.         self.current_entry = None
  273.         self.playing_entry_changed(sp, sp.get_playing_entry())
  274.         self.csi_id = shell.connect('create_song_info', self.create_song_info)
  275.  
  276.     
  277.     def deactivate(self, shell):
  278.         uim = shell.get_ui_manager()
  279.         uim.remove_ui(self.ui_id)
  280.         uim.remove_action_group(self.action_group)
  281.         self.action_group = None
  282.         self.action = None
  283.         sp = shell.get_player()
  284.         sp.disconnect(self.pec_id)
  285.         shell.disconnect(self.csi_id)
  286.         if self.window is not None:
  287.             self.window.destroy()
  288.             self.window = None
  289.         
  290.  
  291.     
  292.     def create_configure_dialog(self, dialog = None):
  293.         if not dialog:
  294.             glade_file = self.find_file('lyrics-prefs.glade')
  295.             dialog = LyricsConfigureDialog(glade_file, gconf_keys).get_dialog()
  296.         
  297.         dialog.present()
  298.         return dialog
  299.  
  300.     
  301.     def playing_entry_changed(self, sp, entry):
  302.         if entry is not None:
  303.             self.action.set_sensitive(True)
  304.             self.update_song_lyrics(entry)
  305.         else:
  306.             self.action.set_sensitive(False)
  307.  
  308.     
  309.     def update_song_lyrics(self, entry):
  310.         if entry == self.current_entry:
  311.             return None
  312.         db = self.shell.get_property('db')
  313.         if self.window is None:
  314.             return None
  315.         title = db.entry_get(entry, rhythmdb.PROP_TITLE)
  316.         artist = db.entry_get(entry, rhythmdb.PROP_ARTIST)
  317.         self.window.s_title(title, artist)
  318.         lyrics_grabber = LyricGrabber(db, entry)
  319.         lyrics_grabber.search_lyrics(self.window.buffer.set_text)
  320.  
  321.     
  322.     def show_song_lyrics(self, action, shell):
  323.         if self.window is not None:
  324.             self.window.destroy()
  325.             self.window = None
  326.         
  327.         db = shell.get_property('db')
  328.         sp = shell.get_player()
  329.         entry = sp.get_playing_entry()
  330.         if entry is None:
  331.             return None
  332.         title = db.entry_get(entry, rhythmdb.PROP_TITLE)
  333.         artist = db.entry_get(entry, rhythmdb.PROP_ARTIST)
  334.         self.window = LyricWindow()
  335.         self.window.s_title(title, artist)
  336.         self.window.connect('destroy', self.window_deleted)
  337.         lyrics_grabber = LyricGrabber(db, entry)
  338.         lyrics_grabber.search_lyrics(self.window.buffer.set_text)
  339.  
  340.     
  341.     def window_deleted(self, window):
  342.         print 'lyrics window destroyed'
  343.         self.window = None
  344.  
  345.     
  346.     def create_song_info(self, shell, song_info, is_multiple):
  347.         if is_multiple is False:
  348.             x = LyricPane(shell.get_property('db'), song_info)
  349.         
  350.  
  351.  
  352.